<?php

/**
 * Created by PhpStorm.
 * User: 琳飞
 * Created time 2019/12/21 21:21:06
 * E-mail: admin@eyabc.cn
 */

/**
 * Class Sdk
 */
class Sdk
{
    /**
     * Api地址
     * @var string
     */
    protected $url;
    /**
     * 商户ID
     * @var string
     */
    protected $mch_id;
    /**
     * 商户秘钥
     * @var string
     */
    protected $key;

    /**
     * Sdk constructor.
     * @param string $mch_id 商户号
     * @param string $key 商户秘钥
     * @param string $url API地址
     */
    public function __construct($mch_id, $key, $url = 'https://v.e0x.cn/')
    {
        $this->url = rtrim($url, '/') . '/pay';
        $this->mch_id = $mch_id;
        $this->key = $key;
    }

    /**
     * 异步回调验证
     * @access public
     * @return bool
     */
    public function notify()
    {
        if (isset($_POST['sign'])) {
            if ($_POST['sign'] === $this->getSign($_POST)) {
                return $_POST;
            }
        }
        return false;
    }

    /**
     * 订单查询
     * @access public
     * @param string $out_trede_no 订单号
     * @return array
     */
    public function query($out_trede_no)
    {
        // 构造参数数组
        $params = [
            'mch_id' => $this->mch_id,
            'out_trade_no' => $out_trede_no,
        ];
        // 计算签名
        $params['sign'] = $this->getSign($params);
        return $this->request($this->url . '/query', $params);
    }

    /**
     * 订单退款
     * @access public
     * @param string $out_trede_no 订单号
     * @return array
     */
    public function refund($out_trede_no)
    {
        // 构造参数数组
        $params = [
            'mch_id' => $this->mch_id,
            'out_trade_no' => $out_trede_no,
        ];
        // 计算签名
        $params['sign'] = $this->getSign($params);
        return $this->request($this->url . '/refund', $params);
    }

    /**
     * 统一下单
     * @access public
     * @param string $out_trede_no 商户订单号
     * @param integer $total_fee 支付金额
     * @param string $pt 渠道代码
     * @param string $channel 通道代码
     * @param string $notify_url 异步回调地址
     * @param string $subject 商品标题
     * @param string $openid 用户标识
     * @param string|null $sub_mch_id 微信子商户号
     * @return array
     */
    public function order($out_trede_no, $total_fee, $pt, $channel, $notify_url = '', $subject = '', $openid = null, $sub_mch_id = null)
    {
        // 构造参数数组
        $params = [
            'mch_id' => $this->mch_id,
            'out_trade_no' => $out_trede_no,
            'total_fee' => $total_fee,
            'pt' => $pt,
            'channel' => $channel,
            'notify_url' => $notify_url,
            'subject' => $subject,
        ];
        if ($openid) {
            $params['openid'] = $openid;
        }
        if ($sub_mch_id) {
            $params['sub_mch_id'] = $sub_mch_id;
        }
        // 计算签名
        $params['sign'] = $this->getSign($params);
        return $this->request($this->url . '/order', $params);
    }

    /**
     * 获取OpenidUrl
     * @access public
     * @param string $url 回调地址
     * @param string|null $sub_mch_id 微信子商户号
     * @return string
     */
    public function getOpenidUrl($url, $sub_mch_id = null)
    {
        // 构造参数数组
        $params = [
            'mch_id' => $this->mch_id,
            'callback' => $url,
            'sub_mch_id' => $sub_mch_id,
        ];
        // 计算签名
        $params['sign'] = $this->getSign($params);
        return $this->url . '/openid?' . http_build_query($params);
    }

    /**
     * 计算签名
     * @access public
     * @param array $params
     * @return string
     */
    protected function getSign($params)
    {
        $signPars = "";
        ksort($params);
        foreach ($params as $k => $v) {
            if ("sign" !== $k && "" !== trim($v) && $v !== null) {
                $signPars .= $k . "=" . $v . "&";
            }
        }
        $signPars .= "key=" . $this->key;
        $sign = strtoupper(md5($signPars));
        return $sign;
    }

    /**
     * 发送Curl请求
     * @access protected
     * @param string $url
     * @param array $params
     * @return array
     */
    protected function request($url, $params = [])
    {
        list($body, $err) = $this->getCurl($url, $params);
        if ($body) {
            if ($ret = json_decode($body, true)) {
                if ($ret['status'] === 0) {
                    return [$ret, null];
                } else {
                    return [false, $ret['message']];
                }
            } else {
                return [false, '解析JSON数据失败'];
            }
        } else {
            return [false, $err];
        }
    }

    /**
     * 发送Curl请求
     * @access protected
     * @param string $url
     * @param array|string $post
     * @return array
     */
    protected function getCurl($url, $post = null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        if ($post) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        }
        curl_setopt($ch, CURLOPT_USERAGENT, 'Chrome 42.0.2311.135');
        curl_setopt($ch, CURLOPT_ENCODING, "gzip");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $ret = curl_exec($ch);
        $err = curl_error($ch);
        curl_close($ch);
        if ($err) {
            return [false, $err];
        } else {
            return [$ret, null];
        }
    }

}